package com.cloud.basic.tree;

import java.util.Stack;

/**
 * @program: basic
 * @description:
 *        对于树的前序遍历过程，我们每到达一个节点，就会访问该节点，所以这个节点就会直接被访问掉，从而无须保存到栈中。
 *        因为没有将节点的保存到栈中，所以为了保证不丢失节点的右节点的信息，所以我们需要将访问过的节点的右孩子保存到栈中。
 *        对于树的中序遍历过程，由于需要一个栈将到达该节点的中序遍历最先需要访问的节点的路上的节点保存到栈中，然后对于访问掉那个节点后，
 *        他的左子树和本身可以直接丢弃，而代码可以直接进入他的右子树，所以中序遍历的过程中栈保存的节点都是，
 *        通往左子树的最左节点的路径上的节点。
 *        对于树的后续遍历，由于要多次经过每个节点，所以要设置一个状态变量来指示到达一个节点后是进入右子树，
 *        还是他是从右子树返回的不再需要进入右子树了。
 * @author: Cloud
 * @create: 2020/12/7 16:26:04
 */
public class bintree1 {

    NodeType root = null;
    static int i = 0;
    private int[] arr;

    public NodeType buildTree() {
        int j = arr[i];
        NodeType nodeType = new NodeType();
        if (j == 0) return null;
        nodeType.value = j;
        i++;
        nodeType.left = buildTree();
        i++;
        nodeType.right = buildTree();
        return nodeType;
    }

    public void preOrder() {
        Stack stack = new Stack();
        stack.push(root);
        NodeType t;
        while (!stack.isEmpty()) {
            t = (NodeType) stack.pop();
            while (t != null) {
                if (t.right != null) {
                    stack.push(t.right);
                }
                t = t.left;
            }
        }
    }

    public void midTraversal() {
        Stack a = new Stack();

        NodeType t = root;
        while (t != null || !a.isEmpty()) {
            while (t != null) {
                a.push(t);
                t = t.left;
            }
            t = (NodeType) a.pop();
            System.out.println(t.value);
            t = t.right;
        }
    }

    public void postorderTraversal() {
        int[] sign = new int[20];
        Stack stack = new Stack();
        NodeType t = new NodeType();
        t = root;
        if (t == null)
            return;

        while (t != null) {
            stack.push(t);
            sign[stack.size() - 1] = 0;
            t = t.left;
        }
        while (!stack.isEmpty()) {
            t = (NodeType) stack.peek();

            while (t.right != null && sign[stack.size() - 1] == 0) {
                sign[stack.size() - 1] = 1;
                t = t.right;
                while (t != null) {
                    stack.push(t);
                    sign[stack.size() - 1] = 0;
                    t = t.left;
                }
                t = (NodeType) stack.peek();

            }
            System.out.println(t.value);
            stack.pop();
        }
    }

    public static void main(String[] args) {
        int[] a = {1,2,3, 0,4,0,0, 5,6,0,0,0,7,8,0,10,0,0,9 , 0, 0};
        /*                             1
         *                          2     7
         *                       3     5  8  9
         *                         4 6      10
         */

        bintree1 tree = new bintree1();
        tree.arr = a;
        Integer i = 0;
        tree.root = tree.buildTree();
        tree.postorderTraversal();
    }

    class NodeType {
        NodeType left, right;
        int value;

        public NodeType(int value) {
            this.value = value;
            left = null;
            right = null;
        }

        public NodeType() {
        }
    }
}
